﻿using System;
using Common.Logging;
using SimpleServiceBus.Endpoint;
using SimpleServiceBus.Endpoint.Metadata;
using SimpleServiceBus.Messages.Management;
using SimpleServiceBus.Utilities;

namespace SimpleServiceBus.Bus.Pipeline.PipelineComponents.MessageLogging
{
    public abstract class MessageLoggerBase : EndpointServiceBase, IMessageLogger
    {
        public void LogMessage(IMessageContext messageContext, MessageLoggingLevel logLevel)
        {
            try
            {
                if (logLevel == MessageLoggingLevel.None)
                    return;

                MessageLogEntry entry = CreateMessageLogEntry(messageContext.MessageEnvelope, logLevel);

                PersistLogEntry(entry,messageContext,logLevel);

            }
            catch (Exception ex)
            {
                OnMessageLoggingError(messageContext, logLevel, ex);
            }
        }

        protected virtual MessageLogEntry CreateMessageLogEntry(MessageEnvelope message, MessageLoggingLevel logLevel)
        {
            var entry = new MessageLogEntry
                            {
                                MessageID = message.MessageID
                            };

            if (logLevel == MessageLoggingLevel.None)
                return entry;

            if (logLevel == MessageLoggingLevel.HeadersAndBody || logLevel == MessageLoggingLevel.HeadersOnly)
            {
                foreach (string key in message.Headers.Keys)
                    entry.Headers.Add(String.Format("{0} = {1}", key, message.Headers[key]));
            }

            if (logLevel == MessageLoggingLevel.HeadersAndBody || logLevel == MessageLoggingLevel.BodyOnly)
                entry.Message = message.Body;

            return entry;
        }

        protected abstract void PersistLogEntry(MessageLogEntry logEntry,IMessageContext messageContext,MessageLoggingLevel loggingLevel);
        

        protected virtual void OnMessageLoggingError(IMessageContext messageContext,MessageLoggingLevel logLevel,Exception exception)
        {
            ILog log = LogManager.GetLogger(typeof (MessageLoggerBase));
            log.Error(String.Format("Error logging {0} message {1}, Log Level {2}: {3}",
                                    messageContext.MessagePipeline.PipelineDirection,
                                    messageContext.MessageEnvelope.MessageID, logLevel, exception.FullMessage()));
        }

        protected override void StartService()
        {
        }

        protected override void ShutDownService()
        {
        }
    }
}
